package com.kitty.common.start;

import com.kitty.common.cache.RedisService;
import com.kitty.common.cache.service.AppPropertiesService;
import com.kitty.common.schedule.ScheduledService;
import com.kitty.common.thread.NamedThreadFactory;
import com.kitty.game.ServerService;
import com.kitty.game.utils.AsktaoUtil;
import com.kitty.mina.MessageDispatcher;
import com.kitty.mina.ServerSocketIoHandler;
import com.kitty.mina.codec.SerializerHelper;
import com.kitty.mina.filter.*;
import com.kitty.mina.message.MessageFactory;
import com.kitty.mina.task.TaskHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.buffer.SimpleBufferAllocator;
import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
import org.apache.mina.core.service.SimpleIoProcessorPool;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.DefaultSocketSessionConfig;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioProcessor;
import org.apache.mina.transport.socket.nio.NioSession;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
//import com.kitty.mina.message.IMessageDispatcher;
//import java.util.concurrent.ThreadFactory;


@Component
@Slf4j
public class GameServer implements CommandLineRunner {


    private static SocketAcceptor acceptor;
    @Autowired
    ServerService serverService;
    @Autowired
    ScheduledService scheduledService;
    @Autowired
    RedisService redisService;
    @Autowired
    AppPropertiesService appPropertiesService;
    @Override
    public void run(String... var1) throws Exception {
        initGameServer();
    }

    private void initGameServer() throws Exception {
        log.info("Starting GameServer ......");
        MessageFactory.INSTANCE.initMessagePool("com.kitty");
        //初始化消息工作线程池
        TaskHandlerContext.INSTANCE.initialize();
        IoBuffer.setUseDirectBuffer(false);
        IoBuffer.setAllocator(new SimpleBufferAllocator());

        Executor executor = Executors.newCachedThreadPool(new NamedThreadFactory("SOCKET-IO-PROCESSOR"));

        int coreSize = Runtime.getRuntime().availableProcessors();
        if (coreSize > 16) {
            coreSize = 16;
        }
        SimpleIoProcessorPool<NioSession> processor = new SimpleIoProcessorPool<NioSession>(NioProcessor.class, executor, coreSize, null);
        acceptor = new NioSocketAcceptor(processor);
        acceptor.setReuseAddress(true);
        SocketSessionConfig config = new DefaultSocketSessionConfig();
        config.setKeepAlive(false);
        config.setTcpNoDelay(true);
        config.setReuseAddress(true);
        config.setReadBufferSize(1024 * 2);
        config.setIdleTime(IdleStatus.BOTH_IDLE, 30000);
        config.setSoLinger(0);
        acceptor.getSessionConfig().setAll(config);
        DefaultIoFilterChainBuilder filterChain = acceptor.getFilterChain();
        filterChain.addLast("codec", new ProtocolCodecFilter(SerializerHelper.getInstance().getCodecFactory()));
        filterChain.addLast("moduleEntrance", new ModuleEntranceFilter());
        filterChain.addLast("msgTrace", new MessageTraceFilter());
//        filterChain.addLast("flood", new FloodFilter());
        /**聊天过滤*/
        filterChain.addLast("chat", new ChatMessageFilter());
        /**心跳判断*/
        filterChain.addLast("heartBeat", new HeartbeatFilter());
        /**协议计次*/
        filterChain.addLast("moduleCounter", new ModuleCounterFilter());

        //指定业务逻辑处理器
        acceptor.setHandler(new ServerSocketIoHandler(MessageDispatcher.getInstance()));
        // 最多支持1000人连接
        acceptor.setBacklog(800);
        //启动监听
    
        //设置端口号
        try {
            acceptor.setDefaultLocalAddress(new InetSocketAddress(serverService.getPort()));
            acceptor.bind();
        }catch (Exception e){
            System.out.println("e = " + e);
        }
        log.info("socket server start at port:{},", serverService.getPort());
  
        AsktaoUtil.serverStartTime = System.currentTimeMillis();


        log.info("start GameServer success!!");
    }

    public SocketAcceptor getAcceptor() {
        return acceptor;
    }
}
